/* This example demonstrates how to customize movement freedom and backface
 * culling.
 *
 * By default, bodies only will move on x and y axis, and rotate only
 * aroud the z axis. To modify it, the block "movement freedom" should be used.
 * This block consists of the "linear" and "angular" attributes, each one
 * receiving 3 booleans, to set if movement in each axis is allowed or not.
 *
 * When a body has backface culling activated, it will be hidden when
 * it's not facing the camera. It's deactivated by default.
 *
 * It can be tested with edje_player slave mode
 * $ edje_player -S -p physics_backcull.edj
 *
 * signal on backcull -> allow movement in all axes, enable backface cull
 * signal off backcull -> allow movement in all axes, disable backface cull
 *
 * message 1 FLOAT_SET 3 50 -100 0 -> apply an impulse on red box with
 *    x = 50, y = -100, z = 0, for example
 * message 2 FLOAT_SET 3 0 0 8.2 -> apply a torque impulse on red box with
 *    x = 4, y = 0, z = 0.8, for example
 * message 3 FLOAT_SET 3 0 1 0 -> allow linear movement on axes x, y, z
 * message 4 FLOAT_SET 3 0 1 0 -> allow angular movement on axes x, y, z
 * message 5 STRING "linear" -> return a message with part's movement freedom
 *                              for "linear" or "angular.
 */

#define ID_IMPULSE (1)
#define ID_TORQUE_IMPULSE (2)
#define ID_LIN_SET (3)
#define ID_ANG_SET (4)
#define ID_GET (5)

collections {

   group {
      name: "example_group";

      script {
         public message(Msg_Type:type, id, ...) {
            if ((id == ID_IMPULSE) && (type == MSG_FLOAT_SET)) {
               new Float:x, Float:y, Float:z;
               new n = numargs();
               if (n < 5) return;
               x = getfarg(2);
               y = getfarg(3);
               z = getfarg(4);
               physics_impulse(PART:"red_box", x, y, z);
            }
            else if ((id == ID_TORQUE_IMPULSE) && (type == MSG_FLOAT_SET)) {
               new Float:x, Float:y, Float:z;
               new n = numargs();
               if (n < 5) return;
               x = getfarg(2);
               y = getfarg(3);
               z = getfarg(4);
               physics_torque_impulse(PART:"red_box", x, y, z);
            }
            else if ((id == ID_LIN_SET) && (type == MSG_FLOAT_SET)) {
               new Float:x, Float:y, Float:z;
               new n = numargs();
               if (n < 5) return;
               x = getfarg(2);
               y = getfarg(3);
               z = getfarg(4);
               custom_state(PART:"red_box", "default", 0.0);
               set_state_val(PART:"red_box", STATE_PHYSICS_MOV_FREEDOM_LIN,
                  x, y, z);
               set_state(PART:"red_box", "custom", 0.0);
            }
            else if ((id == ID_ANG_SET) && (type == MSG_FLOAT_SET)) {
               new Float:x, Float:y, Float:z;
               new n = numargs();
               if (n < 5) return;
               x = getfarg(2);
               y = getfarg(3);
               z = getfarg(4);
               custom_state(PART:"red_box", "default", 0.0);
               set_state_val(PART:"red_box", STATE_PHYSICS_MOV_FREEDOM_ANG,
                  x, y, z);
               set_state(PART:"red_box", "custom", 0.0);
            }
            else if ((id == ID_GET) && (type == MSG_STRING)) {
               new Float:x, Float:y, Float:z;
               new name[1024];
               getsarg(2, name, sizeof(name));
               if (!strcmp(name, "linear"))
               {
                  get_state_val(PART:"red_box",
                     STATE_PHYSICS_MOV_FREEDOM_LIN, x, y, z);
                  send_message(MSG_STRING_FLOAT_SET, 1, "Linear", x, y, z);
               }
               else if (!strcmp(name, "angular"))
               {
                  get_state_val(PART:"red_box",
                     STATE_PHYSICS_MOV_FREEDOM_ANG, x, y, z);
                  send_message(MSG_STRING_FLOAT_SET, 1, "Angular", x, y, z);
               }
            }
         }
      }

      parts {
         part {
            name: "background";
            type: RECT;
            physics_body: NONE;
            description {
               state: "default" 0.0;
               color: 255 255 255 255; /* white */
               rel1.relative: 0.0 0.0;
               rel2.relative: 1.0 1.0;
            }
         }

         part {
            name: "red_box";
            type: RECT;
            physics_body: RIGID_BOX;
            description {
               state: "default" 0.0;
               color: 255 0 0 255; /* light red */
               rel1.relative: 0.45 0.1;
               rel2.relative: 0.55 0.2;
               aspect: 1 1;
               physics {
                  mass: 30;
                  restitution: 0.85;
                  movement_freedom {
                     linear: 1 1 1;
                     angular: 1 1 1;
                  }
               }
            }
            description {
               state: "backface_culled" 0.0;
               inherit: "default" 0.0;
               physics.backface_cull: 1;
            }
         }

         part {
            name: "floor";
            type: RECT;
            physics_body: BOUNDARY_BOTTOM;
            description {
               state: "default" 0.0;
               visible: 0;
               physics {
                  restitution: 0.8;
               }
            }
         }

         part {
            name: "front";
            type: RECT;
            physics_body: BOUNDARY_FRONT;
            description {
               state: "default" 0.0;
               visible: 0;
               physics {
                  restitution: 0.4;
               }
            }
         }

         part {
            name: "back";
            type: RECT;
            physics_body: BOUNDARY_BACK;
            description {
               state: "default" 0.0;
               visible: 0;
               physics {
                  restitution: 0.4;
               }
            }
         }

         part {
            name: "left";
            type: RECT;
            physics_body: BOUNDARY_LEFT;
            description {
               state: "default" 0.0;
               visible: 0;
               physics {
                  restitution: 0.4;
               }
            }
         }

         part {
            name: "right";
            type: RECT;
            physics_body: BOUNDARY_RIGHT;
            description {
               state: "default" 0.0;
               visible: 0;
               physics {
                  restitution: 0.4;
               }
            }
         }
      }

      programs {
         program {
            name: "backcull,on";
            signal: "on";
            source: "backcull";
            action: STATE_SET "backface_culled" 0.0;
            target: "red_box";
         }

         program {
            name: "backcull,off";
            signal: "off";
            source: "backcull";
            action: STATE_SET "default" 0.0;
            target: "red_box";
         }

      }

   }
}
